home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
hypercrd
/
hc2_x
/
regnpckg.sit
/
BitMapToRegion ƒ
/
BitMapRgn.c
next >
Wrap
Text File
|
1990-12-10
|
10KB
|
329 lines
/*
>> BitMapRgn.c, June 90 <<
>> <<
>> Nigel Perry, np@doc.ic.ac.uk <<
>> Dept of Computing, Imperial College, 180 Queens Gate, <<
>> London SW7 2BZ, England <<
>> <<
>> Version of the BitMapRgn trap (0xA8D7) which is not in all systems <<
>> This C/asm version is an extension of a C routine written <<
>> by Juri Munkki in April 89. Added error checks, now works with a <<
>> BitMap with any origin, used assembler for speed <<
>> <<
>> Juri Munkki, jmunkki@kampi.hut.fi <<
>> Helsinki University of Technology Computing Centre <<
>> Otakaari 1 U044B, SF02150 Espoo, Finland <<
>> <<
>> This program is in the PUBLIC DOMAIN. <<
*/
/* Define TRAPATCH if trap patch version (project BMTR Trap ╣).
Will compile a TRAP resource and write it to BMTR XCMD ╣.rsrc,
to use in the BMTR Patcher.╣ & BMTR Init.╣ this TRAP resource must be
copied with ResEdit to the appropriate ╣.rsrc file. DO NOT change this
project to write directly to another ╣.rsrc file, they contain other
resources which you will DESTROY.
*/
#define TRAPATCH
#include <asm.h>
#define _BitMapToRegion 0xA8D7
#define _Unimplemented 0xA89F
#define rgnTooBigErr -500
#ifdef TRAPATCH
#define BitMapRgn main
/* CODE header */
header()
{ extern pascal OSErr BitMapRgn();
asm
{ bra.s @1 ; header
dc.b 'n','p','9','0' ; header + 2
dc.b 'j','u','r','i' ; header + 6
@1: jmp BitMapRgn
}
}
#endif TRAPATCH
/*
>> Convert a bitmap into a region.
*/
pascal OSErr BitMapRgn(RgnHandle, BitMap *);
pascal OSErr BitMapRgn(Target, Bits)
RgnHandle Target;
BitMap *Bits;
{ int *TargetBase; /* StripAddress(*Target) */
int *RowStart; /* Index of first x value on row */
int TargetSize,RgnSize; /* Size in data words & bytes */
Rect TempRect,RgnBounds; /* Temporary & region bounds rects */
BitMap RowBitMap; /* Working bitmap with one row in it */
int i; /* Row counter in a "for" loop */
int diff;
int left;
/* three address registers a2-4 */
register int *TargetP; /* Pointer to region data array */
register int *MaxTarget; /* Memory management stuff */
#ifndef TRAPATCH
register long *BitP; /* Pointer to current line */
#else
/* need to force a4 in LSC CODE resource */
#define BitP a4
#endif
/* five data registers d3-7 */
register int shiftcount; /* shift count for BitWord */
register long BitWord; /* current 32 bits of line */
register int x; /* Column counter in a "for" loop */
register int pixelstatus; /* Flag is false if last pixel is white */
register int right;
#ifdef TRAPATCH
/* save a4 in patch */
asm
{ move.l a4,-(a7)
}
#endif
asm
{ move.l #4096,d0 /* Initial guess for final region size */
move.w d0,TargetSize
move.l Target,a0 /* Allocate initial data buffer */
_SetHandleSize
bne @bomb /* Did we run out of RAM? 0=failure. */
_HLock /* HLock((Handle)Target); */
/* TargetP points to region data */
move.l Target,a0 /* TargetBase = StripAddres(*(Handle)Target) */
move.l (a0),d0
_StripAddress
move.l d0,a0
move.l d0,TargetBase
lea 10(a0),TargetP /* TargetP = (TargetBase + 10); */
/* A safe maximum value for our index */
move.w TargetSize,d0
lea -8(a0,d0.w),MaxTarget /* MaxTarget = TargetBase + TargetSize - 8; */
/* Set region bounds to nothing: */
move.l #0x7FFF7FFF,RgnBounds.top /* SetRect(&RgnBounds,32767,32767,-32767,-32767); */
move.l #0x80018001,RgnBounds.bottom
/* Set up a bitmap with a single line: */
move.l Bits,a0
move.w OFFSET(BitMap,bounds)+OFFSET(Rect,left)(a0),TempRect.left /* Set up left & right bounds */
move.w OFFSET(BitMap,bounds)+OFFSET(Rect,right)(a0),TempRect.right
move.w OFFSET(BitMap,bounds)+OFFSET(Rect,top)(a0),d0
move.w d0,TempRect.top; /* Single row bitmap with height = 1 */
addq.w #1,d0
move.w d0,TempRect.bottom
move.l TempRect.top,RowBitMap.bounds.top /* RowBitMap.bounds=TempRect; */
move.l TempRect.bottom,RowBitMap.bounds.bottom;
moveq #15,d0 /* RowBitMap.rowBytes = ((TempRect.width + 15) >> 4) << 1; */
add.w TempRect.right,d0
sub.w TempRect.left,d0
asr.w #4,d0
asl.w #1,d0
move.w d0,RowBitMap.rowBytes
ext.w d0 /* RowBitMap.baseAddr = NewPtr(RowBitMap.rowBytes); */
_NewPtr
bne @bomb
move.l a0,RowBitMap.baseAddr
}
/* Start out with the first line of the source bitmap */
CopyBits(Bits,&RowBitMap,&TempRect,&RowBitMap.bounds,srcCopy,0);
asm
{ /* right = Bits->bounds.right; */
move.l Bits,a0
move.w OFFSET(BitMap,bounds)+OFFSET(Rect,right)(a0),right
move.w OFFSET(BitMap,bounds)+OFFSET(Rect,left)(a0),left
/* i = Bits->bounds.bottom - Bits->bounds.top; */
move.w OFFSET(BitMap,bounds)+OFFSET(Rect,bottom)(a0),d0
sub.w OFFSET(BitMap,bounds)+OFFSET(Rect,top)(a0),d0
move.w d0,i
}
for(; i >= 0; i--) /* For every line and more */
{ /* Row data starts with Y value*/
asm
{ move.w TempRect.top,(TargetP)+ /* *TargetP++ = TempRect.top; */
}
RowStart = TargetP; /* X values on row start here */
pixelstatus = 0; /* Pixels outside bitmap are white */
asm
{ move.l RowBitMap.baseAddr,BitP /* BitP = (long *)RowBitMap.baseAddr; */
}
shiftcount = 0;
for(x = left; x<right; x++)
{ asm
{ tst.w shiftcount
bne.s @nextBit
moveq #32,shiftcount
move.l (BitP)+,BitWord /* BitWord = *BitP++; */
@nextBit
subq.w #1,shiftcount
/* Test for a change */
/* if((BitTst(RowBitMap.baseAddr,x)!=0) != pixelstatus) */
lsl.l #1,BitWord
scs d0
eor.b pixelstatus,d0
beq @elselab
}
{ asm
{ /* Color changed */
not.b pixelstatus /* pixelstatus = !pixelstatus; */
/* Record x coordinate */
move.w x,(TargetP)+ /* *TargetP++ = x; */
}
if(TargetP >= MaxTarget) /* Is the buffer full? */
{ asm
{ move.l TargetP,d0 /* diff = TargetP - TargetBase; */
sub.l TargetBase,d0
move.w d0,diff
add.w #2048,TargetSize /* Enlarge the buffer */
bvc.s @sizeOk /* if((TargetSize+=2048) > 32767) */
move.w #rgnTooBigErr,d0
bra @bomb2
@sizeOk
move.l Target,a0 /* Unlock to change size */
_HUnlock
move.w TargetSize,d0 /* Change the size */
ext.l d0
_SetHandleSize
bne @bomb2 /* No success? */
_HLock /* Lock it again */
move.l Target,a0 /* TargetBase = StripAddress(*(Handle)Target); */
move.l (a0),d0
_StripAddress
move.l d0,TargetBase
move.l d0,TargetP
adda.w diff,TargetP /* TargetP = TargetBase + diff; */
/* New maximum index */
subq.l #8,d0
move.l d0,MaxTarget /* MaxTarget= TargetBase + TargetSize; */
adda.w TargetSize,MaxTarget
}
}
}
elselab:
;
}
if(pixelstatus) /* Last pixel was black, record edge */
asm
{ move.w x,(TargetP)+ /* *TargetP++=x; */
}
if(RowStart==TargetP) /* Row was empty (no changes) */
TargetP--; /* Remove Y value from data */
else
{ /* Check for new region bounds: */
asm
{ move.l RowStart,a0 /* if(*RowStart < RgnBounds.left) */
move.w (a0),d0
cmp.w RgnBounds.left,d0
bge.s @else1
move.w d0,RgnBounds.left /* RgnBounds.left = *RowStart; */
@else1
move.w -2(TargetP),d0 /* if(TargetP[-1] > RgnBounds.right) */
cmp.w RgnBounds.right,d0
ble.s @else2
move.w d0,RgnBounds.right /* RgnBounds.right = TargetP[-1]; */
@else2
}
RgnBounds.bottom = TempRect.top;
/* Write an "end of line" flag */
asm
{ move.w #32767,(TargetP)+ /* *TargetP++ = 32767; */
}
}
/* Copy current line into the single line bitmap: */
if(i>0) CopyBits(Bits,&RowBitMap,&TempRect,&RowBitMap.bounds,srcCopy,0);
TempRect.top++; TempRect.bottom++; /* Move one line down */
/* If we are still inside the bitmap, XOR this line with the previous line:*/
if(i>1) CopyBits(Bits,&RowBitMap,&TempRect,&RowBitMap.bounds,srcXor,0);
}
/* RgnBounds.top = TargetBase[5]; */ /* Top boundary is first recorded Y coordinate */
asm
{ move.l TargetBase,a0 ; (*)
move.w 10(a0),RgnBounds.top
}
/* If the region is empty, set the bounds rect to an empty rectangle: */
if(RgnBounds.right<=RgnBounds.left || RgnBounds.bottom<=RgnBounds.top)
asm
{ clr.l RgnBounds.top /* SetRect(&RgnBounds,0,0,0,0); */
clr.l RgnBounds.bottom
}
asm
{ /* Write an "end of region" flag */
move.w #32767,(TargetP)+ /* *TargetP++ = 32767; */
/* Calculate region size.*/
move.l TargetP,d0 /* RgnSize = (TargetP - TargetBase) * 2; */
; sub.l TargetBase,d0 /* result must be <= 32767 */
sub.l a0,d0 ; TargetBase is in a0 (*)
cmp.w #28,d0 /* if(RgnSize<=28) RgnSize=10; */
bgt.s @3
moveq #10,d0 /* Rectangular or empty region is only a Rect */
@3: move.w d0,RgnSize ; (**)
/* Store region bounds rectangle */
/* ((RgnPtr)TargetBase)->rgnBBox=RgnBounds; */
; move.l TargetBase,a0 already in a0 (*)
move.l RgnBounds.top,OFFSET(Region,rgnBBox)+OFFSET(Rect,top)(a0)
move.l RgnBounds.bottom,OFFSET(Region,rgnBBox)+OFFSET(Rect,bottom)(a0)
/* Store region size (low 16 bits) */
/* ((RgnPtr)TargetBase)->rgnSize=RgnSize; */
move.w d0,OFFSET(Region,rgnSize)(a0) ; RgnSize is in d0 (**)
}
asm
{ /* Unlock our target region. */
move.l Target,a0 /* HUnlock((Handle)Target); */
_HUnlock
/* Resize region to optimally small */
move.w RgnSize,d0
ext.l d0
_SetHandleSize /* SetHandleSize((Handle)Target,RgnSize); */
bne.s @bomb2 /* shouldn't occur... */
}
asm
{ move.l RowBitMap.baseAddr,a0 /* DisposPtr(RowBitMap.baseAddr) */
_DisposPtr
bne.s @bomb
bra.s @done /* return noErr */
bomb2:
move.w d0,-(a7)
move.l RowBitMap.baseAddr,a0
_DisposPtr
bra.s @bomb3
bomb:
move.w d0,-(a7)
bomb3:
move.l Target,a0
move.l a0,-(a7)
_HUnlock /* may still be locked */
_SetEmptyRgn
move.w (a7)+,d0
done:
#ifdef TRAPATCH
; get a4 back
move.l (a7)+,a4
#endif
}
}